package com.xyht.sca_s.student_manage_system.modules.attendance.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xyht.sca_s.student_manage_system.common.commonReturn.CommonCodeEnum;
import com.xyht.sca_s.student_manage_system.common.commonReturn.CommonResult;
import com.xyht.sca_s.student_manage_system.common.commonReturn.ResponseResult;
import com.xyht.sca_s.student_manage_system.common.util.CacheUtil;
import com.xyht.sca_s.student_manage_system.common.util.TimeUtil;
import com.xyht.sca_s.student_manage_system.modules.attendance.entity.SmsAttendance;
import com.xyht.sca_s.student_manage_system.modules.attendance.entity.SmsAttendanceDetail;
import com.xyht.sca_s.student_manage_system.modules.attendance.entity.SmsAttendanceEvent;
import com.xyht.sca_s.student_manage_system.modules.attendance.entity.req.SmsAttendanceDetailReq;
import com.xyht.sca_s.student_manage_system.modules.attendance.entity.resp.SmsAttendanceDetailResp;
import com.xyht.sca_s.student_manage_system.modules.attendance.entity.resp.SmsAttendanceResp;
import com.xyht.sca_s.student_manage_system.modules.attendance.entity.resp.SmsStudentAttendanceResp;
import com.xyht.sca_s.student_manage_system.modules.attendance.mapper.SmsAttendanceDetailMapper;
import com.xyht.sca_s.student_manage_system.modules.attendance.mapper.SmsAttendanceEventMapper;
import com.xyht.sca_s.student_manage_system.modules.attendance.mapper.SmsAttendanceMapper;
import com.xyht.sca_s.student_manage_system.modules.attendance.service.SmsAttendanceDetailService;
import com.xyht.sca_s.student_manage_system.modules.newTips.util.NewTipsUtil;
import com.xyht.sca_s.student_manage_system.modules.org.entity.SmsOrgStructure;
import com.xyht.sca_s.student_manage_system.modules.org.mapper.SmsOrgStructureMapper;
import com.xyht.sca_s.student_manage_system.modules.websocket.entity.WebsocketResult;
import com.xyht.sca_s.student_manage_system.modules.websocket.myEnum.WebsocketResultEnum;
import com.xyht.sca_s.student_manage_system.modules.websocket.service.WebSocketService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import static com.xyht.sca_s.student_manage_system.common.util.ParamCheckUtil.isNullOrEmpty;
import static com.xyht.sca_s.student_manage_system.modules.attendance.constant.AttendanceStatusConstant.*;
import static com.xyht.sca_s.student_manage_system.modules.attendance.constant.AttendanceTaskStatusConstant.ATTENDANCE_TASK_STATUS_CLOSE;
import static com.xyht.sca_s.student_manage_system.modules.attendance.constant.AttendanceTaskStatusConstant.ATTENDANCE_TASK_STATUS_OPEN;

/**
 * <p>
 * 考勤打卡详情 服务实现类
 * </p>
 *
 * @author XYHT
 * @since 2023-02-23
 */
@Service
public class SmsAttendanceDetailServiceImpl extends ServiceImpl<SmsAttendanceDetailMapper, SmsAttendanceDetail> implements SmsAttendanceDetailService {
    @Autowired
    private SmsAttendanceMapper smsAttendanceMapper;
    @Autowired
    private CacheUtil cacheUtil;
    @Autowired
    private SmsAttendanceDetailMapper smsAttendanceDetailMapper;
    @Autowired
    private SmsOrgStructureMapper smsOrgStructureMapper;
    @Autowired
    private WebSocketService webSocketService;
    @Autowired
    private SmsAttendanceEventMapper smsAttendanceEventMapper;
    @Autowired
    private NewTipsUtil newTipsUtil;

    @Override
    public ResponseResult studentSignInAttendance(SmsAttendanceDetailReq smsAttendanceDetailReq, String user_id) {
        if (isNullOrEmpty(smsAttendanceDetailReq.getAttendanceId()) || isNullOrEmpty(smsAttendanceDetailReq.getLongitude())
                || isNullOrEmpty(smsAttendanceDetailReq.getLatitude())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        SmsAttendance smsAttendance = smsAttendanceMapper.selectOne(new QueryWrapper<SmsAttendance>()
                .lambda()
                .eq(SmsAttendance::getId, smsAttendanceDetailReq.getAttendanceId())
                .gt(SmsAttendance::getEndTime, new Date()));//未过期
        if (smsAttendance == null || smsAttendance.getId() == null) {
            return CommonResult.failed(CommonCodeEnum.ATTENDANCE_NOT_EXIST_OR_OVERTIME);
        }

        SmsAttendanceDetail smsAttendanceDetail = new SmsAttendanceDetail();
        smsAttendanceDetail.setAttendanceId(smsAttendanceDetailReq.getAttendanceId());
        smsAttendanceDetail.setLongitude(smsAttendanceDetailReq.getLongitude());
        smsAttendanceDetail.setLatitude(smsAttendanceDetailReq.getLatitude());
        smsAttendanceDetail.setAttendanceStatus(ATTENDANCE_STATUS_SIGN_IN_CHECKING);
        smsAttendanceDetail.setSignTime(new Date());

        int resultCount = smsAttendanceDetailMapper.update(smsAttendanceDetail, new QueryWrapper<SmsAttendanceDetail>()
                .lambda()
                .eq(SmsAttendanceDetail::getAttendanceId, smsAttendanceDetailReq.getAttendanceId())
                .eq(SmsAttendanceDetail::getStuId, user_id));
        if (resultCount == 0) {
            return CommonResult.failed(CommonCodeEnum.ATTENDANCE_SIGN_IN_FAIL);
        }

        //websocket实时更新
        SmsAttendanceDetail socketDetail = smsAttendanceDetailMapper.selectOne(new QueryWrapper<SmsAttendanceDetail>()
                .lambda()
                .eq(SmsAttendanceDetail::getAttendanceId, smsAttendanceDetailReq.getAttendanceId())
                .eq(SmsAttendanceDetail::getStuId, user_id));
        SmsAttendanceDetailResp detailResp = new SmsAttendanceDetailResp();
        BeanUtils.copyProperties(socketDetail, detailResp);
        webSocketService.singleSend(smsAttendance.getAttendanceUserId(),
                null,
                WebsocketResult.success(WebsocketResultEnum.ATTENDANCE_SING_IN_STATUS_UPDATE, detailResp));

        //消息通知
        newTipsUtil.dealFinishTips(smsAttendanceDetailReq.getAttendanceId(),
                user_id);

        return CommonResult.success();
    }

    @Override
    public ResponseResult teacherUpdateAttendanceDetail(SmsAttendanceDetailReq smsAttendanceDetailReq, String user_id) {
        if (isNullOrEmpty(smsAttendanceDetailReq.getId()) || isNullOrEmpty(smsAttendanceDetailReq.getAttendanceId())
                || isNullOrEmpty(smsAttendanceDetailReq.getAttendanceStatus())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        if (smsAttendanceDetailReq.getAttendanceStatus() != ATTENDANCE_STATUS_TAB_NORMAL) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        SmsAttendance smsAttendance = smsAttendanceMapper.selectOne(new QueryWrapper<SmsAttendance>()
                .lambda()
                .eq(SmsAttendance::getId, smsAttendanceDetailReq.getAttendanceId())
                .eq(SmsAttendance::getAttendanceUserId, user_id));
        if (smsAttendance == null || smsAttendance.getId() == null) {
            return CommonResult.failed(CommonCodeEnum.ATTENDANCE_UPDATE_DENY);
        }

        SmsAttendanceDetail smsAttendanceDetail = new SmsAttendanceDetail();
        smsAttendanceDetail.setId(smsAttendanceDetailReq.getId());
        smsAttendanceDetail.setAttendanceStatus(smsAttendanceDetailReq.getAttendanceStatus());
        smsAttendanceDetail.setSignTime(new Date());
        smsAttendanceDetailMapper.updateById(smsAttendanceDetail);
        return CommonResult.success();
    }

    @Override
    public ResponseResult getSignInAttendanceDetail(String attendance_id, String user_id) {
        if (isNullOrEmpty(attendance_id)) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        SmsAttendanceDetail smsAttendanceDetail = smsAttendanceDetailMapper.selectOne(new QueryWrapper<SmsAttendanceDetail>()
                .lambda()
                .eq(SmsAttendanceDetail::getStuId, user_id)
                .eq(SmsAttendanceDetail::getAttendanceId, attendance_id));
        if (smsAttendanceDetail == null || smsAttendanceDetail.getId() == null) {
            return CommonResult.failed(CommonCodeEnum.ATTENDANCE_SIGN_IN_NOT_EXIST);
        }

        SmsAttendance smsAttendance = smsAttendanceMapper.selectById(attendance_id);
        SmsAttendanceResp smsAttendanceResp = new SmsAttendanceResp();
        BeanUtils.copyProperties(smsAttendance, smsAttendanceResp);
        smsAttendanceResp.setAttendanceStatus(smsAttendanceDetail.getAttendanceStatus());

        //考勤事件获取
        SmsAttendanceEvent smsAttendanceEvent = smsAttendanceEventMapper.selectOne(new QueryWrapper<SmsAttendanceEvent>()
                .lambda()
                .eq(SmsAttendanceEvent::getAttendanceId, attendance_id));
        if (smsAttendanceEvent != null && smsAttendanceEvent.getId() != null) {
            smsAttendanceResp.setAttendanceEvent(smsAttendanceEvent.getEventName());
        }

        //考勤任务状态 剩余考勤时间
        int attendanceStatus;
        int statusTime;
        Date nowDate = new Date();
        long nowTime = nowDate.getTime();
        long endTime = smsAttendance.getEndTime().getTime();
        long leaveTime = endTime - nowTime;
        if (leaveTime <= 0) {
            attendanceStatus = ATTENDANCE_TASK_STATUS_CLOSE;
            statusTime = 0;
        } else {
            attendanceStatus = ATTENDANCE_TASK_STATUS_OPEN;
            statusTime = Math.round((float) leaveTime / 1000);
        }
        smsAttendanceResp.setStatus(attendanceStatus);
        smsAttendanceResp.setStatusTime(statusTime);

        //考勤班级组织
        List<String> attendanceOrg = JSONObject.parseArray(smsAttendanceResp.getAttendanceOrg(), String.class);
        List<String> attendanceOrgName = new ArrayList<>();
        if (attendanceOrg != null && attendanceOrg.size() > 0) {
            attendanceOrgName = attendanceOrg.stream().map(org -> {
                SmsOrgStructure orgStructure = smsOrgStructureMapper.selectById(org);
                return orgStructure.getOrgName();
            }).collect(Collectors.toList());
        }
        smsAttendanceResp.setAttendanceOrg(JSONObject.toJSONString(attendanceOrgName));
        return CommonResult.success(smsAttendanceResp);
    }

    @Override
    public ResponseResult getSignInAttendanceList(Integer pageNum, Integer pageSize,
                                                  String bg_date, String end_date,
                                                  String search_str, String user_id) {
        Date bgDate = null;
        Date endDate = null;
        if (!isNullOrEmpty(bg_date)) {
            bgDate = TimeUtil.StringtoDate(bg_date);
        }
        if (!isNullOrEmpty(end_date)) {
            endDate = TimeUtil.StringtoDate(end_date);
        }

        List<String> attendanceIDList = smsAttendanceDetailMapper.selectList(new QueryWrapper<SmsAttendanceDetail>()
                .lambda()
                .eq(SmsAttendanceDetail::getStuId, user_id)
                .eq(SmsAttendanceDetail::getAttendanceStatus, ATTENDANCE_STATUS_DOING))
                .stream()
                .map(SmsAttendanceDetail::getAttendanceId)
                .collect(Collectors.toList());
        List<SmsStudentAttendanceResp> attendanceRespList = new ArrayList<>();
        int total = 0;
        if (attendanceIDList.size() > 0) {
            Page<SmsAttendance> page = new Page<>(pageNum, pageSize);
            QueryWrapper<SmsAttendance> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda()
                    .in(SmsAttendance::getId, attendanceIDList)
                    .gt(SmsAttendance::getEndTime, new Date());
            if (bgDate != null) {
                queryWrapper.lambda().ge(SmsAttendance::getCreateTime, bgDate);
            }
            if (endDate != null) {
                queryWrapper.lambda().le(SmsAttendance::getCreateTime, endDate);
            }
            if (!isNullOrEmpty(search_str)) {
                queryWrapper.lambda().like(SmsAttendance::getAttendanceName, search_str);
            }
            attendanceRespList = smsAttendanceMapper.selectPage(page, queryWrapper)
                    .getRecords()
                    .stream()
                    .map(attendance -> {
                        SmsStudentAttendanceResp smsAttendanceResp = new SmsStudentAttendanceResp();
                        BeanUtils.copyProperties(attendance, smsAttendanceResp);
                        //考勤任务状态 剩余考勤时间
                        int statusTime;
                        Date nowDate = new Date();
                        long nowTime = nowDate.getTime();
                        long endTime = attendance.getEndTime().getTime();
                        long leaveTime = endTime - nowTime;
                        if (leaveTime <= 0) {
                            statusTime = 0;
                        } else {
                            statusTime = Math.round((float) leaveTime / 1000);
                        }
                        smsAttendanceResp.setStatusTime(statusTime);
                        return smsAttendanceResp;
                    })
                    .collect(Collectors.toList());
            total = (int) page.getTotal();
        }
        return CommonResult.success(attendanceRespList, total);
    }

    @Override
    public ResponseResult getSignInAttendanceHistoryList(Integer pageNum, Integer pageSize,
                                                         String bg_date, String end_date,
                                                         String search_str, Integer attendance_status,
                                                         String user_id) {
        if (attendance_status != null && attendance_status == ATTENDANCE_STATUS_DOING) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        Date bgDate = null;
        Date endDate = null;
        if (!isNullOrEmpty(bg_date)) {
            bgDate = TimeUtil.StringtoDate(bg_date);
        }
        if (!isNullOrEmpty(end_date)) {
            endDate = TimeUtil.StringtoDate(end_date);
        }
        QueryWrapper<SmsAttendanceDetail> detailQueryWrapper = new QueryWrapper<>();
        detailQueryWrapper.lambda()
                .eq(SmsAttendanceDetail::getStuId, user_id);
        if (attendance_status != null) {
            detailQueryWrapper.lambda().eq(SmsAttendanceDetail::getAttendanceStatus, attendance_status);
        } else {
            detailQueryWrapper.lambda().ne(SmsAttendanceDetail::getAttendanceStatus, ATTENDANCE_STATUS_DOING);
        }

        List<SmsAttendanceDetail> detailList = smsAttendanceDetailMapper.selectList(detailQueryWrapper);
        List<String> attendanceIDList = detailList.stream()
                .map(SmsAttendanceDetail::getAttendanceId)
                .collect(Collectors.toList());
        List<SmsStudentAttendanceResp> attendanceRespList = new ArrayList<>();
        int total = 0;
        if (attendanceIDList.size() > 0) {
            Page<SmsAttendance> page = new Page<>(pageNum, pageSize);
            QueryWrapper<SmsAttendance> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda()
                    .in(SmsAttendance::getId, attendanceIDList)
//                    .lt(SmsAttendance::getEndTime, new Date())
                    .orderByDesc(SmsAttendance::getCreateTime);
            if (bgDate != null) {
                queryWrapper.lambda().ge(SmsAttendance::getCreateTime, bgDate);
            }
            if (endDate != null) {
                queryWrapper.lambda().le(SmsAttendance::getCreateTime, endDate);
            }
            if (!isNullOrEmpty(search_str)) {
                queryWrapper.lambda().like(SmsAttendance::getAttendanceName, search_str);
            }
            attendanceRespList = smsAttendanceMapper.selectPage(page, queryWrapper)
                    .getRecords()
                    .stream()
                    .map(attendance -> {
                        SmsStudentAttendanceResp smsAttendanceResp = new SmsStudentAttendanceResp();
                        BeanUtils.copyProperties(attendance, smsAttendanceResp);
                        //考勤任务状态 剩余考勤时间
                        int statusTime;
                        Date nowDate = new Date();
                        long nowTime = nowDate.getTime();
                        long endTime = attendance.getEndTime().getTime();
                        long leaveTime = endTime - nowTime;
                        if (leaveTime <= 0) {
                            statusTime = 0;
                        } else {
                            statusTime = Math.round((float) leaveTime / 1000);
                        }
                        smsAttendanceResp.setStatusTime(statusTime);

                        List<SmsAttendanceDetail> filterDetail = detailList.stream()
                                .filter(detail -> detail.getAttendanceId().equals(attendance.getId()))
                                .collect(Collectors.toList());
                        smsAttendanceResp.setAttendanceStatus(filterDetail.get(0).getAttendanceStatus());
                        return smsAttendanceResp;
                    })
                    .collect(Collectors.toList());
            total = (int) page.getTotal();
        }
        return CommonResult.success(attendanceRespList, total);
    }
}
